home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / Visual Cafe Pro v1.0 / SOURCE.BIN / Calendar.java < prev    next >
Encoding:
Java Source  |  1997-06-19  |  18.2 KB  |  623 lines

  1. package symantec.itools.awt.util;
  2.  
  3.  
  4. import java.awt.Panel;
  5. import java.awt.Dimension;
  6. import java.awt.Color;
  7. import java.awt.Event;
  8. import java.awt.Font;
  9. import java.awt.Rectangle;
  10. import java.awt.Graphics;
  11. import java.awt.FontMetrics;
  12. import java.awt.Container;
  13. import java.util.Date;
  14. import symantec.itools.awt.ComboBox;
  15. import symantec.itools.awt.NumericSpinner;
  16.  
  17. //    01/29/97    TWB    Integrated changes from Windows
  18. //    01/30/07    RKM    Changed invalidates to repaint
  19. //                    Changed logic in paint
  20. //                        1)sc.setBackground is called, only if the colors are different
  21. //                        2)sc.paint is called instead of repaint
  22. //                    Made setDate actually work
  23.  
  24. /**
  25.  * Calendar component.  Creates a graphic calendar displaying a month of dates.
  26.  * A combo box controls the month displayed, a numeric spin control changes the
  27.  * year displayed.
  28.  *
  29.  *
  30.  * @version 1.0, Nov 26, 1996
  31.  *
  32.  * @author  Symantec
  33.  *
  34.  */
  35.  
  36.  
  37. public class Calendar
  38.     extends Panel
  39. {
  40.     private ComboBox combo;
  41.     private boolean bNeedsPlatformHelp;
  42.     private NumericSpinner sc;
  43.     private Date dCurrent;
  44.     private Date dLast;
  45.     private Color selectedColor;
  46.     private String cal[][];
  47.     private int dateSelectedx = -1;
  48.     private int dateSelectedy = -1;
  49.     private int lastSelectedDate = -1;
  50.     private int maxMonthx = -1;
  51.     private int maxMonthy = -1;
  52.     private int firstDay = -1;
  53.     private int topRow = -1;
  54.     private int selectHeight = -1;
  55.     private int centerNumber = -1;
  56.     private int heightAdjust = -1;
  57.     private int numberAdjust = -1;
  58.  
  59.     /**
  60.      * Creates a default calendar with today's
  61.      * date initialized.
  62.      */
  63.     public Calendar()
  64.     {
  65.         this(new Date());
  66.     }
  67.  
  68.     /**
  69.      * Creates a calendar with the specified date initialized.
  70.      * @param defaultdate the date to be shown initially
  71.      */
  72.     public Calendar(Date defaultdate)
  73.     {
  74.         setLayout(null);
  75.         bNeedsPlatformHelp = ComboBox.needsPlatformHelp();  // help comboBar change state
  76.  
  77.         dCurrent = defaultdate;
  78.         dLast = dCurrent;
  79.         combo = new ComboBox();
  80.         combo.addItem("January");
  81.         combo.addItem("February");
  82.         combo.addItem("March");
  83.         combo.addItem("April");
  84.         combo.addItem("May");
  85.         combo.addItem("June");
  86.         combo.addItem("July");
  87.         combo.addItem("August");
  88.         combo.addItem("September");
  89.         combo.addItem("October");
  90.         combo.addItem("November");
  91.         combo.addItem("December");
  92.         add(combo);
  93.         sc = new NumericSpinner();
  94.         add(sc);
  95.         sc.setMin(1900);
  96.         sc.setMax(9999);
  97.         sc.setCurrent(1900 + dCurrent.getYear());
  98.         sc.setEditable(false);
  99.  
  100.         combo.select(dCurrent.getMonth());
  101.         if (symantec.itools.lang.OS.isMacintosh())
  102.             selectedColor = Color.black;
  103.         else
  104.             selectedColor = Color.blue;
  105.  
  106.         if (!symantec.itools.lang.OS.isMacintosh())  //12/18/96  Andy McFarland some platforms don't want their fonts hardwired...
  107.         {
  108.             if (bNeedsPlatformHelp)  // different fonts to help display problems.
  109.                 setFont(new Font("Dialog", Font.PLAIN, 9));
  110.             else
  111.                 setFont(new Font("Dialog", Font.BOLD, 10));
  112.         }
  113.     }
  114.  
  115.     /**
  116.      * Returns the date that the calendar is set to.
  117.      * @return the current value of the calendar.
  118.      */
  119.     public String getDate()
  120.     {
  121.         return dCurrent.toString();
  122.     }
  123.  
  124.     /**
  125.      * Sets the date selected on the calendar.
  126.      * @param date the date that the calendar is to be set to
  127.      */
  128.     public void setDate(String date)
  129.     {
  130.         //Convert string to Date
  131.         Date newDate;
  132.         try {
  133.             newDate = new Date(date);
  134.         } catch (Exception e) {
  135.             newDate = new Date();
  136.         }
  137.  
  138.         if (!dCurrent.equals(newDate))
  139.         {
  140.             dCurrent = newDate;
  141.  
  142.             combo.select(dCurrent.getMonth());
  143.             sc.setCurrent(1900 + dCurrent.getYear());
  144.  
  145.             //Trigger re calculation
  146.             firstDay = -1;
  147.             lastSelectedDate = -1;
  148.  
  149.             repaint();
  150.         }
  151.     }
  152.  
  153.     /**
  154.      * Returns the color that highlights the selected date on the calendar.
  155.      * @return the current selected color.
  156.      */
  157.     public Color getSelectedColor()
  158.     {
  159.         return selectedColor;
  160.     }
  161.  
  162.     /**
  163.      * Sets the color used to highlight the selected date on the calendar.
  164.      * @param c the color that the selected color is to be set to
  165.      */
  166.     public void setSelectedColor(Color c)
  167.     {
  168.         if (!selectedColor.equals(c))
  169.         {
  170.             selectedColor = c;
  171.  
  172.             repaint();
  173.         }
  174.     }
  175.  
  176.     /**
  177.      * Processes events for this component.
  178.      * This is a standard Java AWT method which gets called by the AWT
  179.      * to handle this component's events. The default handler for
  180.      * components dispatches to one of the following methods as needed:
  181.      * action(), gotFocus(), lostFocus(), keyDown(), keyUp(), mouseEnter(),
  182.      * mouseExit(), mouseMove(), mouseDrag(), mouseDown(), or mouseUp().
  183.      *
  184.      * @param event the event to handle
  185.      * @return true if the event was handled and no further action is needed,
  186.      * false to pass the event to this component's parent
  187.      * @see java.awt.Component#action
  188.      * @see java.awt.Component#gotFocus
  189.      * @see java.awt.Component#lostFocus
  190.      * @see java.awt.Component#keyDown
  191.      * @see java.awt.Component#keyUp
  192.      * @see java.awt.Component#mouseEnter
  193.      * @see java.awt.Component#mouseExit
  194.      * @see java.awt.Component#mouseMove
  195.      * @see java.awt.Component#mouseDrag
  196.      * @see java.awt.Component#mouseDown
  197.      * @see java.awt.Component#mouseUp
  198.      */
  199.     public boolean handleEvent(Event event)
  200.     {
  201.         int topRow = -1;
  202.  
  203.         switch(event.id)
  204.         {
  205.             case Event.MOUSE_DOWN:
  206.             {
  207.                 if (bNeedsPlatformHelp) // Solaris machines have different drawing levels
  208.                 {
  209.                     topRow = 70;
  210.                     centerNumber = 14;
  211.                     heightAdjust = 6;
  212.                     numberAdjust = 6;
  213.                 }
  214.                 else
  215.                 {
  216.                     topRow = 40;        // needed for Windows drawing
  217.                     centerNumber = 12;
  218.                     heightAdjust = 2;
  219.                     numberAdjust = 0;
  220.                 }
  221.  
  222.                 Rectangle r = bounds();
  223.                 int blockheight = ((r.height - topRow - 14) / 7);   // 7 rows
  224.                 int blockwidth = (r.width - 32) / 7;                // 7 columns
  225.  
  226.                 if ( ((event.x >= 15) && (event.x < r.width - 15)) &&   // if event in calendar window
  227.                      ((event.y >= topRow + blockheight) && (event.y < r.height - 14)))
  228.                 {
  229.                     dateSelectedx = ((event.x - 16) / blockwidth);
  230.                     dateSelectedy = ((event.y  - topRow - blockheight) / blockheight);
  231.                     repaint();
  232.                     firstDay = -1;
  233.                 }
  234.                 break;
  235.             }
  236.  
  237.             case Event.ACTION_EVENT:
  238.             {
  239.                 // ComboBox list items == month type events
  240.                 if (event.target instanceof ComboBox)
  241.                 {
  242.                     int dy = dCurrent.getDate();
  243.                     int mo = combo.getSelectedIndex();
  244.                     int yr = dCurrent.getYear();
  245.                     dCurrent = new Date(yr, mo, dy);
  246.                     while (dCurrent.getMonth() != mo)
  247.                     {
  248.                         dCurrent = new Date(yr, mo, --dy);
  249.                         lastSelectedDate = -1;
  250.                     }
  251.                     firstDay = -1;
  252.                     repaint();
  253.                 }
  254.  
  255.                 // Spin Control list items == year type events
  256.                 if (event.target == sc)
  257.                 {
  258.                     int dy = dCurrent.getDate();
  259.                     int mo = dCurrent.getMonth();
  260.                     int yr = sc.getCurrent() - 1900;
  261.                     dCurrent = new Date(yr, mo, dy);
  262.                     while (dCurrent.getMonth() != mo)
  263.                     {
  264.                         dCurrent = new Date(yr, mo, --dy);
  265.                         lastSelectedDate = -1;
  266.                     }
  267.                     firstDay = -1;
  268.                     repaint();
  269.                 }
  270.                 break;
  271.             }
  272.         }//switch
  273.  
  274.         return super.handleEvent(event);
  275.     }
  276.  
  277.     boolean isLeapYear(int year)
  278.     {
  279.         if (year% 4 == 0 && (year != 2100))
  280.             return true;
  281.         else
  282.             return false;
  283.     }
  284.  
  285.     /**
  286.      * Moves and/or resizes this component.
  287.      * This is a standard Java AWT method which gets called to move and/or
  288.      * resize this component. Components that are in containers with layout
  289.      * managers should not call this method, but rely on the layout manager
  290.      * instead.
  291.      *
  292.      * @param x horizontal position in the parent's coordinate space
  293.      * @param y vertical position in the parent's coordinate space
  294.      * @param width the new width
  295.      * @param height the new height
  296.      */
  297.     public void reshape(int x, int y, int width, int height)
  298.     {
  299.         sc.reshape(width - 100, 7, 100, 30);
  300.         super.reshape(x, y, width, height);
  301.     }
  302.  
  303.     /**
  304.      * Handles redrawing of this component on the screen.
  305.      * This is a standard Java AWT method which gets called by the Java
  306.      * AWT (repaint()) to handle repainting this component on the screen.
  307.      * The graphics context clipping region is set to the bounding rectangle
  308.      * of this component and its <0,0> coordinate is this component's
  309.      * top-left corner.
  310.      * Typically this method paints the background color to clear the
  311.      * component's drawing space, sets graphics context to be the foreground
  312.      * color, and then calls paint() to draw the component.
  313.      *
  314.      * It is overridden here to reduce flicker by eliminating the uneeded
  315.      * clearing of the background.
  316.      *
  317.      * @param g the graphics context
  318.      * @see java.awt.Component#repaint
  319.      * @see #paint
  320.      */
  321.     public void update(Graphics g)
  322.     {
  323.         paint(g);
  324.     }
  325.  
  326.     /**
  327.      * Paints this component using the given graphics context.
  328.      * This is a standard Java AWT method which typically gets called
  329.      * by the AWT to handle painting this component. It paints this component
  330.      * using the given graphics context. The graphics context clipping region
  331.      * is set to the bounding rectangle of this component and its <0,0>
  332.      * coordinate is this component's top-left corner.
  333.      *
  334.      * @param g the graphics context used for painting
  335.      * @see java.awt.Component#repaint
  336.      * @see #update
  337.      */
  338.     public void paint(Graphics g)
  339.     {
  340.         //If the background of the sc is different, set it
  341.         if (!sc.getBackground().equals(getBackground()))
  342.             sc.setBackground(getBackground());
  343.         sc.paint(g);
  344.  
  345.         FontMetrics fm = getFontMetrics(getFont());
  346.  
  347.         Rectangle r = bounds();
  348.  
  349.         if (symantec.itools.lang.OS.isMacintosh())  // Using layout managers might have obviated most
  350.         {                                            // of this coordinate tweaking - Andy
  351.             combo.reshape(12, 10, 100, 20);
  352.             topRow = 40;
  353.             selectHeight = fm.getHeight();
  354.             centerNumber = 14;
  355.             heightAdjust = 2;
  356.             numberAdjust = 0;
  357.         }
  358.         else
  359.         {
  360.             if (bNeedsPlatformHelp)
  361.             {   // Solaris parameters
  362.                 combo.reshape(12, 20, 100, 34);
  363.                 //sc.reshape(r.width - 90, 20, 80, 34);
  364.                 topRow = 70;
  365.                 selectHeight = fm.getHeight() + 2;
  366.                 centerNumber = 14;
  367.                 heightAdjust = 6;
  368.                 numberAdjust = 6;
  369.             }
  370.             else
  371.             {   // windows parameters
  372.                 combo.reshape(12, 10, 100, 25);
  373.                 topRow = 40;
  374.                 selectHeight = fm.getHeight();
  375.                 centerNumber = 12;
  376.                 heightAdjust = 2;
  377.                 numberAdjust = 0;
  378.             }
  379.         }
  380.  
  381.         int blockwidth = (r.width - 32) / 7;                // 7 columns
  382.         int blockheight = ((r.height - topRow - 16) / 7);   // 7 rows
  383.         int xloc = blockwidth - (fm.stringWidth("S") / 2);  //average location in block
  384.         int yloc = topRow + centerNumber;
  385.         if (dateSelectedx < 0)
  386.         {
  387.             // top
  388.             g.setColor(Color.black);
  389.             g.drawLine(15, topRow, r.width-17, topRow);
  390.  
  391.             // bottom
  392.             g.setColor(Color.lightGray);
  393.             g.drawLine(15, topRow + (7 * blockheight), r.width-18, topRow + (7 * blockheight));
  394.             g.setColor(Color.white);
  395.             g.drawLine(16, topRow + 1 + (7 * blockheight), r.width-17, topRow + 1 + (7 * blockheight));
  396.  
  397.             // left
  398.             g.setColor(Color.black);
  399.             g.drawLine(15, topRow, 15, topRow + (7 * blockheight));
  400.  
  401.             // right
  402.             g.setColor(Color.lightGray);
  403.             g.drawLine(r.width-17, topRow, r.width-17, topRow + (7 * blockheight));
  404.             g.setColor(Color.white);
  405.             g.drawLine(r.width-16, topRow, r.width-16, topRow + (7 * blockheight));
  406.  
  407.             // fill box
  408.             if (symantec.itools.lang.OS.isMacintosh())  // Using layout managers might have obviated most
  409.             {
  410.                 g.fillRect(16, topRow + (blockheight) , r.width-33, (6 * blockheight) );
  411.                 g.setColor(Color.gray);
  412.                 g.fillRect(16, topRow+1, r.width-32, blockheight+1 );
  413.             }
  414.             else
  415.             {
  416.                 g.fillRect(16, topRow + (blockheight), r.width-33, (6 * blockheight) + 1);
  417.                 g.setColor(Color.gray);
  418.                 g.fillRect(16, topRow + 1, r.width-32, blockheight-2);
  419.             }
  420.  
  421.             // letters on top
  422.             g.setColor(Color.white);
  423.  
  424.             if (symantec.itools.lang.OS.isMacintosh())
  425.             {
  426.                 yloc += (blockheight+1)/2 - fm.getHeight()/2; // Lets have the day labels track resizes
  427.                                                            // in the component like the numbers do...
  428.                 g.drawString("S", xloc, yloc - 1);
  429.                 xloc = (2 * blockwidth) - (fm.stringWidth("M") / 2);
  430.                 g.drawString("M", xloc, yloc - 1);
  431.                 xloc = (3 * blockwidth) - (fm.stringWidth("T") / 2);
  432.                 g.drawString("T", xloc, yloc - 1);
  433.                 xloc = (4 * blockwidth) - (fm.stringWidth("W") / 2);
  434.                 g.drawString("W", xloc, yloc - 1);
  435.                 xloc = (5 * blockwidth) - (fm.stringWidth("T") / 2);
  436.                 g.drawString("T", xloc, yloc - 1);
  437.                 xloc = (6 * blockwidth) - (fm.stringWidth("F") / 2);
  438.                 g.drawString("F", xloc, yloc - 1);
  439.                 xloc = (7 * blockwidth) - (fm.stringWidth("S") / 2);
  440.                 g.drawString("S", xloc, yloc - 1);
  441.             }
  442.             else
  443.             {
  444.                 g.drawString("S", xloc, yloc - 1);
  445.                 xloc = (2 * blockwidth) - (fm.stringWidth("M") / 2);
  446.                 g.drawString("M", xloc, yloc - 1);
  447.                 xloc = (3 * blockwidth) - (fm.stringWidth("T") / 2);
  448.                 g.drawString("T", xloc, yloc - 1);
  449.                 xloc = (4 * blockwidth) - (fm.stringWidth("W") / 2);
  450.                 g.drawString("W", xloc, yloc - 1);
  451.                 xloc = (5 * blockwidth) - (fm.stringWidth("T") / 2);
  452.                 g.drawString("T", xloc, yloc - 1);
  453.                 xloc = (6 * blockwidth) - (fm.stringWidth("F") / 2);
  454.                 g.drawString("F", xloc, yloc - 1);
  455.                 xloc = (7 * blockwidth) - (fm.stringWidth("S") / 2);
  456.                 g.drawString("S", xloc, yloc - 1);
  457.             }
  458.         }
  459.  
  460.         Date dMonthStart;
  461.         // must be run twice for Solaris
  462.         dMonthStart = new Date(dCurrent.getYear(), dCurrent.getMonth(), 1);
  463.         dMonthStart = new Date(dCurrent.getYear(), dCurrent.getMonth(), 1);
  464.  
  465.         // which date does month begin?
  466.         if (firstDay < 0)
  467.             firstDay = dMonthStart.getDay();
  468.         int initdate = -1;
  469.         int caldate = 1;
  470.         int templastdate = -1;
  471.         int month = dCurrent.getMonth() + 1;
  472.  
  473.         // which date already selected
  474.         if (lastSelectedDate < 1) initdate = dCurrent.getDate();
  475.         else if (dateSelectedx < 0) initdate = lastSelectedDate;
  476.  
  477.         // paint calendar
  478.         g.setColor(Color.black);
  479.  
  480.     calendar:
  481.  
  482.         for (int j = 0; j < 6; j++)
  483.         {
  484.             for (int i = 0; i < 7; i++)
  485.             {
  486.                 if ((maxMonthy < dateSelectedy) || (maxMonthy == dateSelectedy && maxMonthx < dateSelectedx))
  487.                 {   //click after end date
  488.                     dateSelectedx = -1;
  489.                     dateSelectedy = -1;
  490.                     break calendar;
  491.                  }
  492.                 if (j == 0 && i < firstDay)
  493.                 {   // click before the start day
  494.                     if (dateSelectedx == i && dateSelectedy == j)
  495.                     {
  496.                         dateSelectedx = -1;
  497.                         dateSelectedy = -1;
  498.                         break calendar;
  499.                     }
  500.                     else
  501.                     continue;
  502.                 }
  503.  
  504.                 // calculate where to draw
  505.                 xloc = ((i + 1) * blockwidth) - (fm.stringWidth(Integer.toString(caldate)) / 2);
  506.                 yloc = topRow + heightAdjust + 4 + numberAdjust + (((j+2) * blockheight) - fm.getHeight());
  507.  
  508.                 // draw one digit numbers differently from two diget
  509.                 if (dateSelectedx < 0 && initdate != caldate)
  510.                 {
  511.                     if (caldate < 10)
  512.                         g.drawString((Integer.toString(caldate)), xloc , yloc);
  513.                     else
  514.                         g.drawString(Integer.toString(caldate), xloc , yloc);
  515.                 }
  516.                 else if (dateSelectedx == i && dateSelectedy == j || initdate == caldate)
  517.                 {
  518.                     if (dateSelectedx == i && dateSelectedy == j)
  519.                     {
  520.                         // must be run twice for Solaris
  521.                         dCurrent = new Date(dCurrent.getYear(), dCurrent.getMonth(), caldate);
  522.                         dCurrent = new Date(dCurrent.getYear(), dCurrent.getMonth(), caldate);
  523.                     }
  524.                     //draw selected number
  525.                     g.setColor(selectedColor);
  526.                     if (caldate < 10)
  527.                         g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)) + 2, selectHeight);
  528.                     else
  529.                         g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)), selectHeight);
  530.                     g.setColor(Color.white);
  531.                     if (caldate < 10)
  532.                         g.drawString(Integer.toString(caldate), xloc , yloc);
  533.                     else
  534.                         g.drawString(Integer.toString(caldate), xloc , yloc);
  535.                     templastdate = caldate;
  536.                     g.setColor(Color.black);
  537.                 }
  538.                 else if (caldate == lastSelectedDate)
  539.                 {   // unselected previously selected number
  540.                     g.setColor(Color.white);
  541.                     if (caldate < 10)
  542.                         g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)) + 2, selectHeight);
  543.                     else
  544.                         g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)), selectHeight);
  545.                     g.setColor(Color.black);
  546.                     if (caldate < 10)
  547.                         g.drawString(Integer.toString(caldate), xloc , yloc);
  548.                     else
  549.                         g.drawString(Integer.toString(lastSelectedDate), xloc, yloc);
  550.                     lastSelectedDate = -1;
  551.                 }
  552.                 if (caldate >= 31)
  553.                 {
  554.                     maxMonthx = i;
  555.                     maxMonthy = j;
  556.                     break calendar;
  557.                 }
  558.                 else if ((caldate >= 30) && ((month == 4) || (month == 6) || (month == 9) || (month == 11)))
  559.                 {
  560.                     maxMonthx = i;
  561.                     maxMonthy = j;
  562.                     break calendar;
  563.                 }
  564.                 else if ((caldate >= 29) && (month == 2))
  565.                 {
  566.                     maxMonthx = i;
  567.                     maxMonthy = j;
  568.                     break calendar;
  569.                 }
  570.                 else if ((caldate >= 28) && (month == 2) && (!isLeapYear(dCurrent.getYear())))
  571.                 {
  572.                     maxMonthx = i;
  573.                     maxMonthy = j;
  574.                     break calendar;
  575.                 }
  576.                 caldate++;
  577.             }
  578.         }
  579.  
  580.         if (lastSelectedDate < 0)
  581.             lastSelectedDate = templastdate;
  582.  
  583.         dateSelectedx = -1;
  584.         dateSelectedy = -1;
  585.  
  586.         if (!dLast.equals(dCurrent))
  587.         {
  588.             dLast = dCurrent;
  589.             Container c = getParent();
  590.             if (c != null)
  591.                 c.postEvent( new Event(this, Event.ACTION_EVENT, dCurrent) );
  592.         }
  593.     }
  594.  
  595.     /**
  596.      * Returns the recommended dimensions to properly display this component.
  597.      * This is a standard Java AWT method which gets called to determine
  598.      * the recommended size of this component.
  599.      *
  600.      * @return the preferred dimensions for the calender (250 x 200 pixels).
  601.      *
  602.      * @see #minimumSize
  603.      */
  604.     public Dimension preferredSize()
  605.     {
  606.         return (new Dimension(250,200));
  607.     }
  608.  
  609.     /**
  610.      * Returns the minimum dimensions to properly display this component.
  611.      * This is a standard Java AWT method which gets called to determine
  612.      * the minimum size of this component.
  613.      *
  614.      * @return the minimum dimensions needed for the calender (250 x 200 pixels).
  615.      *
  616.      * @see #preferredSize
  617.      */
  618.     public Dimension minimumSize()
  619.     {
  620.         return (new Dimension(250,200));
  621.     }
  622. }
  623.